package com.z_talk.server.core;

import com.z_talk.core.enums.ResponseCodeEnum;
import com.z_talk.core.enums.ResponseEnum;
import com.z_talk.core.message.ResponseMessage;
import com.z_talk.core.model.LoginModel;
import com.z_talk.core.model.PrivateTalkModel;
import com.z_talk.core.model.UserInfo;
import com.z_talk.core.model.UserModel;
import com.z_talk.core.util.CodeUtils;
import com.z_talk.core.vo.LoggerVO;
import com.z_talk.core.vo.NewsVO;
import com.z_talk.server.localization.TalkLocalzation;
import com.z_talk.server.localization.UserLocalzation;
import io.netty.channel.Channel;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;

public class MessageHandler {

    public static CopyOnWriteArrayList<UserModel> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // 注册
    public static void regiterHandler(Channel channel, UserInfo userInfo){
        List<UserInfo> userInfoList = UserLocalzation.loadUserList();
        if (userInfoList == null){
            userInfoList = new ArrayList<>();
        }
        String userId = CodeUtils.getRandom();

        for (int i = 0; i < 5; i++) {
            if (check(userInfoList,userId)){
                break;
            }
            userId = CodeUtils.getRandom();
        }
        userInfo.setUserId(userId);

        userInfoList.add(userInfo);
        ResponseMessage responseMessage = new ResponseMessage();
        responseMessage.setMessageType(ResponseEnum.REGISTER_RESPONSE);
        Map<String,Object> attr = new HashMap<>();
        if (UserLocalzation.saveUser(userInfoList)){
            responseMessage.setCodeEnum(ResponseCodeEnum.Y);
            LoggerVO loggerVO = new LoggerVO(userInfo.getNickName()+"注册成功");
            ServerMain.serverView.updateLogger(loggerVO.getLogger());
            ServerMain.serverView.updateRegister();
        }else{
            responseMessage.setCodeEnum(ResponseCodeEnum.N);
        }
        responseMessage.setAttribute(attr);
        attr.put(ResponseEnum.REGISTER_RESPONSE.getAttr(), userInfo.getNickName()+"注册成功,\n您的账号为："+userId+",请记好");
        // 发送请求响应
        channel.writeAndFlush(responseMessage);
    }

    private static boolean check(List<UserInfo> userInfoList, String userId) {

        for (int i = 0; i < userInfoList.size(); i++) {
            if (userInfoList.get(i).getUserId().equals(userId)){
                return false;
            }
        }
        return true;
    }


    // 登录
    public static void loginHandler(Channel channel, LoginModel loginVO){
        try {
            UserInfo userInfo = UserLocalzation.userLogin(loginVO);
            ResponseMessage login = new ResponseMessage();
            login.setMessageType(ResponseEnum.LOGIN_RESPONSE);
            Map<String,Object> loginAttr = new HashMap<>();
            Map<String,Object> onlineListAttr = new HashMap<>();
            if (userInfo!=null){
                // 上线通知
                login.setCodeEnum(ResponseCodeEnum.Y);
                ResponseMessage responseMessage = new ResponseMessage();
                responseMessage.setMessageType(ResponseEnum.ONLINE_RESPONSE);
                Map<String,Object> attr = new HashMap<>();
                attr.put(ResponseEnum.ONLINE_RESPONSE.getAttr(),sdf.format(new Date())+"  "+userInfo.getNickName()+"上线了\n");
                responseMessage.setAttribute(attr);
                sendMsg(responseMessage);
                // 保存在线的用户
                UserModel userModel = new UserModel(userInfo,channel);
                copyOnWriteArrayList.add(userModel);
                // 服务器端更新日志信息
                LoggerVO loggerVO = new LoggerVO(userInfo.getNickName()+"登录成功");
                ServerMain.serverView.updateLogger(loggerVO.getLogger());
                // 发送登录成功信息
                loginAttr.put(ResponseEnum.LOGIN_RESPONSE.getAttr(),userInfo);
                ServerMain.serverView.updateOnline();
            }else{
                login.setCodeEnum(ResponseCodeEnum.N);
                LoggerVO loggerVO = new LoggerVO(loginVO.getUserId()+"登录失败");
                ServerMain.serverView.updateLogger(loggerVO.getLogger());
                loginAttr.put(ResponseEnum.LOGIN_RESPONSE.getAttr(),null);
            }
            login.setAttribute(loginAttr);
            channel.writeAndFlush(login);
            // 刷新
            ServerMain.serverView.updateTitleMessage();
            // 发送在线用户列表
            UserInfo[] users = copyOnWriteArrayList.stream().map(item -> {
                return item.getUserInfo();
            }).toArray(UserInfo[]::new);
            ResponseMessage onlineListResponseMessage = new ResponseMessage();
            onlineListResponseMessage.setMessageType(ResponseEnum.ONLINE_LIST_RESPONSE);
            onlineListAttr.put(ResponseEnum.ONLINE_LIST_RESPONSE.getAttr(),users);
            onlineListResponseMessage.setAttribute(onlineListAttr);
            sendMsg(onlineListResponseMessage);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 退出处理
    public static void logoutHandler(Channel channel) {
        copyOnWriteArrayList.forEach(item -> {
            if (item.getChannel() == channel){
                if (item.getUserInfo()!=null){
                    ResponseMessage responseMessage = new ResponseMessage();
                    responseMessage.setMessageType(ResponseEnum.OFFLINE_RESPONSE);
                    Map<String,Object> attr = new HashMap<>();
                    attr.put(ResponseEnum.OFFLINE_RESPONSE.getAttr(),sdf.format(new Date())+"  "+item.getUserInfo().getNickName()+"下线了\n");
                    responseMessage.setAttribute(attr);
                    try {
                        sendMsg(responseMessage);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 保持在线的用户
                    copyOnWriteArrayList.remove(item);
                    LoggerVO loggerVO = new LoggerVO(item.getUserInfo().getNickName()+"已下线");
                    ServerMain.serverView.updateLogger(loggerVO.getLogger());
                    ServerMain.serverView.updateOnline();
                }
            }
        });
        // 发送在线用户列表
        UserInfo[] users = copyOnWriteArrayList.stream().map(item -> {
            return item.getUserInfo();
        }).toArray(UserInfo[]::new);
        ResponseMessage onlineListResponseMessage = new ResponseMessage();
        Map<String,Object> onlineListAttr = new HashMap<>();
        onlineListResponseMessage.setMessageType(ResponseEnum.ONLINE_LIST_RESPONSE);
        onlineListAttr.put(ResponseEnum.ONLINE_LIST_RESPONSE.getAttr(),users);
        onlineListResponseMessage.setAttribute(onlineListAttr);
        try {
            sendMsg(onlineListResponseMessage);
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }
    }

    public static void sendWorldTalk(Channel channel,String msg){
        try {
            ResponseMessage responseMessage = new ResponseMessage();
            responseMessage.setMessageType(ResponseEnum.WORLD_TALK_RESPONSE);
            Map<String,Object> attr = new HashMap<>();
            copyOnWriteArrayList.forEach(item -> {
                if (item.getChannel() == channel){
                    NewsVO newsVO = new NewsVO(item.getUserInfo().getNickName());
                    String message = newsVO.getNews()+"\n"+msg+"\n";
                    LoggerVO loggerVO = new LoggerVO(item.getUserInfo().getNickName()+" 发送消息："+msg);
                    ServerMain.serverView.updateLogger(loggerVO.getLogger());
                    attr.put(ResponseEnum.WORLD_TALK_RESPONSE.getAttr(),message);
                    TalkLocalzation.saveWorldTalk(message);
                }
            });
            responseMessage.setAttribute(attr);
            sendMsg(responseMessage);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param msg
     * @throws InterruptedException
     * 发送群体消息
     */
    public static void sendMsg(Object msg) throws InterruptedException {
        copyOnWriteArrayList.forEach(item -> {
            item.getChannel().writeAndFlush(msg);
        });
    }

    public static void sendPrivateMsg(UserInfo userInfo1,UserInfo userInfo2,Object msg1,Object msg2) throws InterruptedException {
        copyOnWriteArrayList.forEach(item -> {
            if (item.getUserInfo().getUserId().equals(userInfo1.getUserId())){
                item.getChannel().writeAndFlush(msg2);
            }
            if (item.getUserInfo().getUserId().equals(userInfo2.getUserId())){
                item.getChannel().writeAndFlush(msg1);
            }
        });
    }


    public static void sendPrivateTalk(Channel channel, PrivateTalkModel privateTalkModel) {
        try {
            ResponseMessage responseMessage1 = new ResponseMessage();
            ResponseMessage responseMessage2 = new ResponseMessage();

            responseMessage1.setMessageType(ResponseEnum.PRIVATE_TALK_RESPONSE);
            responseMessage2.setMessageType(ResponseEnum.PRIVATE_TALK_RESPONSE);

            Map<String,Object> attr1 = new HashMap<>();
            Map<String,Object> attr2 = new HashMap<>();

            AtomicReference<UserInfo> fromUser = new AtomicReference<>();
            copyOnWriteArrayList.forEach(item -> {
                if (item.getChannel() == channel){
                    fromUser.set(item.getUserInfo());
                    NewsVO newsVO = new NewsVO(item.getUserInfo().getNickName());
                    String message = newsVO.getNews()+"\n"+privateTalkModel.getMessage()+"\n";
                    LoggerVO loggerVO = new LoggerVO(item.getUserInfo().getNickName()+" 发送私人消息给 "+privateTalkModel.getUserInfo().getNickName()+"："+privateTalkModel.getMessage());
                    ServerMain.serverView.updateLogger(loggerVO.getLogger());

                    PrivateTalkModel from1 = new PrivateTalkModel();
                    from1.setUserInfo(item.getUserInfo());
                    from1.setMessage(message);
                    attr1.put(ResponseEnum.PRIVATE_TALK_RESPONSE.getAttr(),from1);
                    PrivateTalkModel from2 = new PrivateTalkModel();
                    from2.setUserInfo(privateTalkModel.getUserInfo());
                    from2.setMessage(message);
                    attr2.put(ResponseEnum.PRIVATE_TALK_RESPONSE.getAttr(),from2);

                    TalkLocalzation.savePrivateTalk(item.getUserInfo(),privateTalkModel.getUserInfo(),message);
                }
            });
            responseMessage1.setAttribute(attr1);
            responseMessage2.setAttribute(attr2);
            sendPrivateMsg(fromUser.get(),privateTalkModel.getUserInfo(),responseMessage1,responseMessage2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
